/*
 * Remmina - The GTK+ Remote Desktop Client
 * Copyright (C) 2010 Vic Lee 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA.
 */

#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <string.h>
#include "remminaappletmenuitem.h"
#include "remminaappletmenu.h"

G_DEFINE_TYPE (RemminaAppletMenu, remmina_applet_menu, GTK_TYPE_MENU)

struct _RemminaAppletMenuPriv
{
    gboolean hide_count;
};

enum
{
    LAUNCH_ITEM_SIGNAL,
    EDIT_ITEM_SIGNAL,
    LAST_SIGNAL
};

static guint remmina_applet_menu_signals[LAST_SIGNAL] = { 0 };

static void
remmina_applet_menu_destroy (RemminaAppletMenu *menu, gpointer data)
{
    g_free (menu->priv);
}

static void
remmina_applet_menu_class_init (RemminaAppletMenuClass *klass)
{
    remmina_applet_menu_signals[LAUNCH_ITEM_SIGNAL] =
        g_signal_new ("launch-item",
            G_TYPE_FROM_CLASS (klass),
            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
            G_STRUCT_OFFSET (RemminaAppletMenuClass, launch_item),
            NULL, NULL,
            g_cclosure_marshal_VOID__OBJECT,
            G_TYPE_NONE, 1,
            G_TYPE_OBJECT);
    remmina_applet_menu_signals[EDIT_ITEM_SIGNAL] =
        g_signal_new ("edit-item",
            G_TYPE_FROM_CLASS (klass),
            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
            G_STRUCT_OFFSET (RemminaAppletMenuClass, edit_item),
            NULL, NULL,
            g_cclosure_marshal_VOID__OBJECT,
            G_TYPE_NONE, 1,
            G_TYPE_OBJECT);
}

static void
remmina_applet_menu_init (RemminaAppletMenu *menu)
{
    menu->priv = g_new0 (RemminaAppletMenuPriv, 1);

    g_signal_connect (G_OBJECT (menu), "destroy", G_CALLBACK (remmina_applet_menu_destroy), NULL);
}

static void
remmina_applet_menu_on_item_activate (RemminaAppletMenuItem *menuitem, RemminaAppletMenu *menu)
{
    g_signal_emit (G_OBJECT (menu), remmina_applet_menu_signals[LAUNCH_ITEM_SIGNAL], 0, menuitem);
}

static GtkWidget*
remmina_applet_menu_add_group (GtkWidget *menu, const gchar *group, gint position, RemminaAppletMenuItem *menuitem,
    GtkWidget **groupmenuitem)
{
    GtkWidget *widget;
    GtkWidget *image;
    GtkWidget *submenu;

    widget = gtk_image_menu_item_new_with_label (group);
    gtk_widget_show (widget);

    image = gtk_image_new_from_icon_name ((menuitem->item_type == REMMINA_APPLET_MENU_ITEM_DISCOVERED ?
        "folder-remote" : "folder"), GTK_ICON_SIZE_MENU);
    gtk_widget_show (image);
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
    gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (widget), TRUE);

    g_object_set_data_full (G_OBJECT (widget), "group", g_strdup (group), g_free);
    g_object_set_data (G_OBJECT (widget), "count", GINT_TO_POINTER (0));
    if (groupmenuitem)
    {
        *groupmenuitem = widget;
    }
    if (position < 0)
    {
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
    }
    else
    {
        gtk_menu_shell_insert (GTK_MENU_SHELL (menu), widget, position);
    }

    submenu = gtk_menu_new ();
    gtk_widget_show (submenu);
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), submenu);

    return submenu;
}

static void
remmina_applet_menu_increase_group_count (GtkWidget *widget)
{
    gint cnt;
    gchar *s;

    cnt = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "count")) + 1;
    g_object_set_data (G_OBJECT (widget), "count", GINT_TO_POINTER (cnt));
    s = g_strdup_printf ("%s (%i)", (const gchar*)g_object_get_data (G_OBJECT (widget), "group"), cnt);
    gtk_menu_item_set_label (GTK_MENU_ITEM (widget), s);
    g_free (s);
}

void
remmina_applet_menu_register_item (RemminaAppletMenu *menu, RemminaAppletMenuItem *menuitem)
{
    g_signal_connect (G_OBJECT (menuitem), "activate",
        G_CALLBACK (remmina_applet_menu_on_item_activate), menu);
}

void
remmina_applet_menu_add_item (RemminaAppletMenu *menu, RemminaAppletMenuItem *menuitem)
{
    GtkWidget *submenu;
    GtkWidget *groupmenuitem;
    GtkMenuItem *submenuitem;
    gchar *s, *p1, *p2;
    GList *childs, *child;
    gint position;
    gint cmp;

    submenu = GTK_WIDGET (menu);
    s = g_strdup (menuitem->group);
    p1 = s;
    p2 = p1 ? strchr (p1, '/') : NULL;
    if (p2) *p2++ = '\0';
    while (p1 && p1[0])
    {
        groupmenuitem = NULL;
        childs = gtk_container_get_children (GTK_CONTAINER (submenu));
        position = -1;
        for (child = g_list_first (childs); child; child = g_list_next (child))
        {
            if (!GTK_IS_MENU_ITEM (child->data)) continue;
            position++;
            submenuitem = GTK_MENU_ITEM (child->data);
            if (gtk_menu_item_get_submenu (submenuitem))
            {
                cmp = g_strcmp0 (p1, (gchar*)g_object_get_data (G_OBJECT (submenuitem), "group"));
                if (cmp == 0)
                {
                    /* Found existing group menu */
                    submenu = gtk_menu_item_get_submenu (submenuitem);
                    groupmenuitem = GTK_WIDGET (submenuitem);
                    break;
                }
                else if (cmp < 0)
                {
                    submenu = remmina_applet_menu_add_group (submenu, p1, position, menuitem, &groupmenuitem);
                    break;
                }
            }
            else
            {
                submenu = remmina_applet_menu_add_group (submenu, p1, position, menuitem, &groupmenuitem);
                break;
            }
        }
        if (!child)
        {
            submenu = remmina_applet_menu_add_group (submenu, p1, -1, menuitem, &groupmenuitem);
        }
        g_list_free (childs);
        if (groupmenuitem && !menu->priv->hide_count)
        {
            remmina_applet_menu_increase_group_count (groupmenuitem);
        }
        p1 = p2;
        p2 = p1 ? strchr (p1, '/') : NULL;
        if (p2) *p2++ = '\0';
    }
    g_free (s);

    childs = gtk_container_get_children (GTK_CONTAINER (submenu));
    position = -1;
    for (child = g_list_first (childs); child; child = g_list_next (child))
    {
        if (!GTK_IS_MENU_ITEM (child->data)) continue;
        position++;
        submenuitem = GTK_MENU_ITEM (child->data);
        if (gtk_menu_item_get_submenu (submenuitem)) continue;
        if (!REMMINA_IS_APPLET_MENU_ITEM (submenuitem)) continue;
        cmp = g_strcmp0 (menuitem->name, REMMINA_APPLET_MENU_ITEM (submenuitem)->name);
        if (cmp <= 0)
        {
            gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), GTK_WIDGET (menuitem), position);
            break;
        }
    }
    if (!child)
    {
        gtk_menu_shell_append (GTK_MENU_SHELL (submenu), GTK_WIDGET (menuitem));
    }
    remmina_applet_menu_register_item (menu, menuitem);
}

GtkWidget*
remmina_applet_menu_new (void)
{
    RemminaAppletMenu *menu;

    menu = REMMINA_APPLET_MENU (g_object_new (REMMINA_TYPE_APPLET_MENU, NULL));

    return GTK_WIDGET (menu);
}

void
remmina_applet_menu_set_hide_count (RemminaAppletMenu *menu, gboolean hide_count)
{
    menu->priv->hide_count = hide_count;
}

void
remmina_applet_menu_populate (RemminaAppletMenu *menu)
{
    GtkWidget *menuitem;
    gchar dirname[256];
    gchar filename[256];
    GDir *dir;
    const gchar *name;

    g_snprintf (dirname, sizeof (dirname), "%s/.remmina", g_get_home_dir ());
    dir = g_dir_open (dirname, 0, NULL);
    if (dir != NULL)
    {
        /* Iterate all remote desktop profiles */
        while ((name = g_dir_read_name (dir)) != NULL)
        {
            if (!g_str_has_suffix (name, ".remmina")) continue;
            g_snprintf (filename, sizeof (filename), "%s/%s", dirname, name);

            menuitem = remmina_applet_menu_item_new (REMMINA_APPLET_MENU_ITEM_FILE, filename);
            remmina_applet_menu_add_item (menu, REMMINA_APPLET_MENU_ITEM (menuitem));
            gtk_widget_show (menuitem);
        }
        g_dir_close (dir);
    }
}

